package com.scs.application.modules.purchase.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.core.entity.DataEntity;
import com.scs.application.core.exception.BusinessException;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.StringUtils;
import com.scs.application.modules.base.entity.Matr;
import com.scs.application.modules.base.entity.MatrUnit;
import com.scs.application.modules.base.entity.PackTemplet;
import com.scs.application.modules.base.entity.PackTempletItem;
import com.scs.application.modules.base.mapper.MatrMapper;
import com.scs.application.modules.base.mapper.MatrUnitMapper;
import com.scs.application.modules.base.service.PackTempletItemService;
import com.scs.application.modules.base.service.PackTempletService;
import com.scs.application.modules.base.util.CommonService;
import com.scs.application.modules.base.util.MatrPassUtil;
import com.scs.application.modules.dept.mapper.ApplyAutoMapper;
import com.scs.application.modules.purchase.dto.OrderItemByPackDTO;
import com.scs.application.modules.purchase.entity.Order;
import com.scs.application.modules.purchase.entity.OrderItem;
import com.scs.application.modules.purchase.mapper.OrderItemMapper;
import com.scs.application.modules.purchase.mapper.OrderMapper;
import com.scs.application.modules.purchase.service.OrderItemService;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单明细 服务实现类
 * </p>
 */
@Service
public class OrderItemServiceImpl extends BaseServiceImpl<OrderItemMapper, OrderItem> implements OrderItemService {
    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private ApplyAutoMapper applyAutoMapper;

    @Autowired
    private PackTempletService packTempletService;

    @Autowired
    private PackTempletItemService packTempletItemService;

    @Autowired
    private MatrPassUtil matrPassUtil;
    @Autowired
    private MatrMapper matrMapper;
    @Autowired
    private MatrUnitMapper matrUnitMapper;

    @Override
    public boolean saveOrUpdate(OrderItem entity) {

        OrderItem orderItem = super.getOne(new QueryWrapper<OrderItem>().eq("order_id", entity.getOrderId()).eq("matr_id", entity.getMatrId()).ne(StringUtils.isNotEmpty(entity.getId()), "id", entity.getId()).last("LIMIT 1"));
        if(orderItem != null) {
            throw new BusinessException("已添加该耗材，无需重复添加");
        }
        boolean success = super.saveOrUpdate(entity);

        String orderId = entity.getOrderId();
        updateOrderAmount(orderId);
        return success;
    }
    @Override
    public boolean removeCascadeByIds(Collection<? extends Serializable> idList) {

        // 查询出明细涉及到的所有订单
        List<String> orderIdList = this.listObjs(Wrappers.<OrderItem>query()
                .select("order_id" ).in("id" , idList).groupBy("order_id"),
                v -> v.toString());
        List<OrderItem> orderItems = this.list(Wrappers.<OrderItem>query().in("id", idList));
        List<String> applyOrderIds = new ArrayList<>();
        for (OrderItem orderItem : orderItems) {
            if (StringUtils.isNotBlank(orderItem.getApplyItemId())) {
                CommonService.updateApplyItemStatus(orderItem.getApplyItemId(),true,"采购删除");
            }
            if (StringUtils.isNotBlank(orderItem.getApplyAutoId())) {
                applyOrderIds.add(orderItem.getApplyAutoId());
            }
        }

        boolean success = super.removeCascadeByIds(idList);
        CommonService.updateApplyInfo(applyOrderIds, -1);
        for (String orderId : orderIdList) {
            updateOrderAmount(orderId);
        }

        return success;
    }

    private void updateOrderAmount(String orderId) {
        Double total = calcOrderPrice(orderId);

        // 修改订单总金额
        Order order = new Order();
        order.setAmount(total).setId(orderId);
        orderMapper.updateById(order);
    }

    private Double calcOrderPrice(String orderId) {
        Double totalAmount = this.getObj(Wrappers.<OrderItem>query().select("ifnull(sum(amount),0.0)" ).eq("order_id" , orderId), v -> {
            if (v == null) {
                return 0.0;
            }
            return Double.valueOf(v.toString());
        });
        return totalAmount;
    }

    @Override
    public Double getSumSkuQty(String startDate, String endDate) {
        return this.baseMapper.getSumSkuQty(startDate, endDate);
    }

    @Override
    public Double getSumAmount(String startDate, String endDate) {
        return this.baseMapper.getSumAmount(startDate, endDate);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addByPack(OrderItemByPackDTO orderItemByPackDTO) {

        if (CollectionUtils.isEmpty(orderItemByPackDTO.getPackTemplets())) {
            throw new BusinessException("请选择跟台包！");
        }

        if (StringUtils.isBlank(orderItemByPackDTO.getOrderId())) {
            throw new BusinessException("当前采购主单信息未保存，请检查！");
        }
        //获取包模板所有id集合
        List<String> packTempletIds = orderItemByPackDTO.getPackTemplets().stream().map(item -> item.getId()).collect(Collectors.toList());
        //查询模板信息
        List<PackTemplet> packTemplets = packTempletService.list(new QueryWrapper<PackTemplet>().in("id", packTempletIds));
        List<OrderItem> orderItemList = new ArrayList<>();
        packTemplets.forEach(item -> {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderId(orderItemByPackDTO.getOrderId())
                    .setMatrId("-1")//跟台包默认耗材id为-1
                    .setMatrName(item.getName())
                    .setMatrType("1")//跟台包
                    .setMatrSpec("")
                    .setPackageUnit("")
                    .setPackageQty(1d)
                    .setPackageRate(1d)
                    .setSkuUnit("包")
                    .setSkuQty(1d)
                    .setSkuPrice(item.getAmount())
                    .setAmount(item.getAmount())
                    .setPackId(item.getId())
                    .setPackageUnit("包");
            boolean success = this.save(orderItem);
            if (success) {
                //根据模板主表id查询所有明细表
                String orderPackId = orderItem.getId();
                List<PackTempletItem> packTempletItem = packTempletItemService.list(new QueryWrapper<PackTempletItem>().eq("pack_templet_id", item.getId()));
                if (CollectionUtils.isEmpty(packTempletItem)) {
                    throw new BusinessException("跟台包%s内未维护耗材，请检查！", item.getName());
                }
                packTempletItem.forEach(s -> {
                    OrderItem orderMatrItem = new OrderItem();
                    BeanUtils.copyProperties(s, orderMatrItem);
                    orderMatrItem.setId(null);
                    orderMatrItem.setOrderId(orderItemByPackDTO.getOrderId())
                            .setOrderItemPackId(orderPackId)
                            .setSkuPrice(s.getAmount() / s.getSkuQty());  //价格
                    orderItemList.add(orderMatrItem);
                });
            }
        });

        //是否禁用耗材校验-跟台包采购
//        matrPassUtil.ckeckMatrPass("warehousing", orderItemList.stream().map(OrderItem::getMatrId).collect(Collectors.toList()));
        updataAmount(orderItemByPackDTO.getOrderId());
        return super.saveOrUpdateBatch(orderItemList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateQty(OrderItem orderItem) {

        OrderItem item = this.baseMapper.selectById(orderItem.getOrderItemPackId());
        PackTempletItem packTempletItem = packTempletItemService.getOne(new QueryWrapper<PackTempletItem>().select("sku_qty", "package_qty")
                .eq("pack_templet_id", item.getPackId())
                .eq("matr_id", orderItem.getMatrId()));

        Optional.ofNullable(packTempletItem).orElseThrow(() -> new BusinessException("该包信息不存在,请检查！"));
        this.update(Wrappers.<OrderItem>update()
                .set("package_qty", orderItem.getPackageQty())
                .set("sku_qty", orderItem.getPackageQty() * (packTempletItem.getSkuQty() / packTempletItem.getPackageQty()))
                .set("amount", orderItem.getPackageQty() * (packTempletItem.getSkuQty() / packTempletItem.getPackageQty()) * orderItem.getSkuPrice())
                .eq("id", orderItem.getId()));
        //更新采购明细跟台包包总金额
        updateOrderItemAmount(orderItem);
        //更新采购主表总金额
        updataAmount(orderItem.getOrderId());
        return true;
    }

    @Override
    public boolean deletePackage(String id) {
        OrderItem orderItem = this.getById(id);

        Optional.ofNullable(orderItem).orElseThrow(() -> new BusinessException(String.format("未找到名称为%s跟台包中", orderItem.getMatrName())));

        List<OrderItem> orderItems = this.list(new QueryWrapper<OrderItem>().select("id").eq("order_item_pack_id", id));
        if (orderItems.isEmpty()) {
            this.removeById(id);
        } else {
            List<String> ids = orderItems.stream().map(DataEntity::getId).collect(Collectors.toList());
            this.removeByIds(ids);
            this.removeById(id);
        }
        updataAmount(orderItem.getOrderId());
        return true;
    }

    @Override
    public boolean deleteMatr(String id) {
        OrderItem orderItem = this.getById(id);

        Optional.ofNullable(orderItem).orElseThrow(() -> new BusinessException(String.format("在跟台包中未找到名称为%s相关的耗材", orderItem.getMatrName())));

        boolean success = this.removeById(id);
        if (success) {
            updateOrderItemAmount(orderItem);
            updataAmount(orderItem.getOrderId());
        }
        return success;
    }

    /**
     * 修改 orderItem表中跟台包金额及单品价格
     *
     * @param orderItem
     */
    private void updateOrderItemAmount(OrderItem orderItem) {
        Map<String, Object> map = this.getMap(new QueryWrapper<OrderItem>().select("sum(amount) as amount").eq("order_item_pack_id", orderItem.getOrderItemPackId()));
        this.update(Wrappers.<OrderItem>update()
                .set("amount", map.get("amount") == null ? 0 : map.get("amount"))
                .set("sku_price", map.get("amount") == null ? 0 : map.get("amount"))
                .eq("id", orderItem.getOrderItemPackId()));
    }

    /**
     * 修改采购单主表中金额
     *
     * @param orderId
     */
    private void updataAmount(String orderId) {
        Map<String, Object> workOrderMap = this.getMap(new QueryWrapper<OrderItem>().select("sum(amount) as amount")
                .eq("order_id", orderId));

        orderMapper.update(null, Wrappers.<Order>update()
                .set("amount", workOrderMap.get("amount") == null ? 0 : workOrderMap.get("amount"))
                .eq("id", orderId));
    }


    /**
     * @Description： 批量保存耗材
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveBatchMatr(List<Serializable> matrIdList, String orderId) {
        List<Matr> matrs = matrMapper.selectBatchIds(matrIdList);
        List<MatrUnit> purchaseUnitMax = matrUnitMapper.getPurchaseUnitMax(Wrappers.<MatrUnit>query()
                .in("matr_id", matrIdList).eq("flag_purchase", 1)
                .eq("flag_disabled", 0).orderByDesc("rate"));
        Map<String, List<MatrUnit>> listMap = purchaseUnitMax.stream().collect(Collectors.groupingBy(MatrUnit::getMatrId));
        List<OrderItem> orderItemSaveList = new ArrayList<>();
        matrs.forEach(matr -> {
            OrderItem newItem = new OrderItem();
            BeanUtils.copyProperties(matr, newItem);
            newItem.setPackageQty(1D);
            newItem.setPackageUnit(matr.getSkuUnit()).setPackageRate(1D);
            newItem.setMatrId(matr.getId()).setMatrName(matr.getName()).setMatrSpec(matr.getSpec()).setMatrModel(matr.getModel())
            .setMatrType("0");
            newItem.setPackageQty(1D);

            List<MatrUnit> matrUnits = listMap.get(matr.getId());
            if (matrUnits != null && matrUnits.size() > 0) {
                MatrUnit matrUnit = matrUnits.get(0);
                newItem.setPackageRate(matrUnit.getRate()).setPackageUnit(matrUnit.getUnit());
            }
            newItem.setSkuQty(newItem.getPackageQty() * newItem.getPackageRate());
            newItem.setAmount(newItem.getSkuQty() * newItem.getSkuPrice()).setId(null);
            newItem.setId(null);
            newItem.setOrderId(orderId);
            orderItemSaveList.add(newItem);
        });
        this.saveBatch(orderItemSaveList);
        updataAmount(orderId);
    }
}
